import { Injectable, Logger } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { BookEntity } from "./book.entity";
import { AuthorEntity } from "./author.entity";
import { CatalogEntity } from "./catalog.entity";
import { BookCreateDto, CatalogCreateDto, CatalogUpdateDto } from "./books.dto";
import { UploadService } from "../tools/upload/upload.service";

@Injectable()
export class BooksService {
	private readonly logger = new Logger(BooksService.name);

	constructor(
		private readonly uploadService: UploadService,
		@InjectRepository(BookEntity)
		private bookRepository: Repository<BookEntity>,
		@InjectRepository(AuthorEntity)
		private authorRepository: Repository<AuthorEntity>,
		@InjectRepository(CatalogEntity)
		private catalogRepository: Repository<CatalogEntity>,
	) { }

	/**
	 * 创建书籍
	 * @param book
	 * @returns
	 */
	async createBook(book: BookCreateDto) {
		const path: string = await this.uploadService.saveFile(book.file)

		const newBook = new BookEntity()
		newBook.name = book.name
		newBook.imageUrl = path
		newBook.introduction = book?.introduction ?? null

		// 关联作者 authors
		const authors = book.authors.split(',')
		const authorIds: number[] = []
		for (const authorName of authors) {
			const authorId = await this.validateAuthor(authorName)
			authorIds.push(authorId)
		}

		newBook.authors = authorIds.map(authorId => ({ id: authorId } as any))

		const savedBook = await this.bookRepository.save(newBook)

		return savedBook.id
	}

	/**
	 * 获取书籍列表
	 * @returns
	 */
	async getBooks() {
		return await this.bookRepository.find({relations: ['authors']})
	}

	/**
	 * 删除书籍
	 * @param bookId
	 * @returns
	 */
	async delBook(bookId: number) {
		const book = await this.bookRepository.findOne({ where: { id: bookId } })

		if (!book) {
			this.logger.error(`书籍id为 ${bookId} 的书籍不存在`)
			return
		}

		// 删除书籍的目录
		await this.delCatalogByBookId(bookId)

		await this.bookRepository.remove(book)
	}

	/**
	 * 验证作者是否存在，不存在则创建
	 * @param authorName 作者名
	 * @returns 作者id
	 */
	async validateAuthor(authorName: string): Promise<number> {
		const author = await this.authorRepository.findOne({ where: { name: authorName } })

		if (!author) {
			return await this.createAuthor(authorName)
		}

		return author.id
	}

	/**
	 * 创建作者
	 * @param authorName 作者名
	 * @returns 作者id
	 */
	async createAuthor(authorName: string): Promise<number> {
		const author = new AuthorEntity()
		author.name = authorName

		const newAuthor = await this.authorRepository.save(author)

		return newAuthor.id
	}

	/**
	 * 创建目录
	 * @param catalog
	 * @returns
	 */
	async createCatalog(catalog: CatalogCreateDto) {
		const newCatalog = new CatalogEntity()
		newCatalog.name = catalog.name
		newCatalog.content = catalog.content
		newCatalog.book = { id: catalog.bookId } as any
		// 根据 bookId 查询 book，判断 book 是否存在
		const book = await this.bookRepository.findOne({ where: { id: catalog.bookId } })

		if (!book) {
			this.logger.error(`书籍id为 ${catalog.bookId} 的书籍不存在`)
			return
		}

		// order 为目录排序，根据 bookId 查询目录数量，作为 order 值
		const count = await this.catalogRepository.count({ where: { book: { id: catalog.bookId } } })
		newCatalog.order = count + 1

		const savedCatalog = await this.catalogRepository.save(newCatalog)

		return savedCatalog.id
	}

	/**
	 * 更新目录
	 * @param catalog
	 */
	async updateCatalog(catalog: CatalogUpdateDto) {
		const newCatalog = await this.catalogRepository.findOne({ where: { id: catalog.id } })

		if (!newCatalog) {
			this.logger.error(`目录id为 ${catalog.id} 的目录不存在`)
			return
		}

		newCatalog.name = catalog.name
		newCatalog.content = catalog.content

		await this.catalogRepository.save(newCatalog)
	}

	/**
	 * 获取目录
	 * @param bookId
	 */
	async getCatalogByBookId(bookId: number) {
		return await this.catalogRepository.find({ where: { book: { id: bookId } } })
	}

	/**
	 * 获取目录下某章节的内容
	 * @param catalogId
	 */
	async getCatalogContent(catalogId: number) {
		return await this.catalogRepository.findOne({ where: { id: catalogId } })
	}

	/**
	 * 删除目录
	 * @param catalogId
	 * @returns
	 */
	async delCatalog(catalogId: number) {
		const catalog = await this.catalogRepository.findOne({ where: { id: catalogId } })

		if (!catalog) {
			this.logger.error(`目录id为 ${catalogId} 的目录不存在`)
			return
		}

		await this.catalogRepository.remove(catalog)
	}

	/**
	 * 根据书籍id删除目录
	 * @param bookId
	 */
	async delCatalogByBookId(bookId: number) {
		await this.catalogRepository.delete({ book: { id: bookId } })
	}


}